package lg.minecraft.plugin.pokedex.gui;

import com.cobblemon.mod.common.pokemon.Species;
import lg.minecraft.plugin.library.inventory.CancelInventoryContext;
import lg.minecraft.plugin.library.inventory.ClickInventoryContext;
import lg.minecraft.plugin.library.inventory.InventoryContext;
import lg.minecraft.plugin.library.inventory.LGInventory;
import lg.minecraft.plugin.pokedex.Generations;
import lg.minecraft.plugin.pokedex.LGPokedex;
import lg.minecraft.plugin.pokedex.PokedexPlayer;
import lg.minecraft.plugin.pokedex.config.GenConfig;
import lg.minecraft.plugin.pokedex.config.GuiItemConfig;
import lg.minecraft.plugin.pokedex.config.RewardConfig;
import lg.minecraft.plugin.pokedex.util.CommandUtil;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author langle__
 * @version 1.0
 */
public class PokedexInventory extends LGInventory {

    private static final Map<Generations, String> map = Map.of(
            Generations.GEN1, "§c关都",
            Generations.GEN2, "§6城都",
            Generations.GEN3, "§e丰缘",
            Generations.GEN4, "§a神奥",
            Generations.GEN5, "§2合众",
            Generations.GEN6, "§3卡洛斯",
            Generations.GEN7, "§b阿罗拉",
            Generations.GEN8, "§5伽勒尔",
            Generations.GEN9, "§d帕底亚",
            Generations.ALL_GEN, "§x§f§f§0§0§0§0全§x§f§f§5§5§0§0部§x§f§f§a§a§0§0世§x§f§f§f§f§0§0代"
     );

    private static final int[] GLASS_ARRAY = {51, 52, 53};
    private static final int MAX_PAGE = 45;

    private final Generations generations;
    private final List<Species> speciesList;

    private Map<Species, RewardConfig.PokemonEntry> pokemonRewardMap;
    private List<Species> filterSpeciesList;
    private int listSize;
    private int totalPages;

    private boolean hidePokemon = false;
    private boolean hideAirPokemon = false;
    private boolean hideReceivedPokemon = false;
    private int page = 0;

    public PokedexInventory(Generations generations) {
        super(6, map.get(generations));
        this.generations = generations;
        this.speciesList = GenConfig.INSTANCE.getSpeciesByGen(generations);
        this.filterSpeciesList = speciesList;
        updateSpeciesList();
    }

    @Override
    public void onInventoryOpen(CancelInventoryContext context) {
        Player player = context.getPlayer();
        inventory.clear();
        int startIndex = page * MAX_PAGE;
        int endIndex = Math.min(startIndex + MAX_PAGE, listSize);

        PokedexPlayer pokedexPlayer = LGPokedex.getPokedexPlayerManger().getPokedexPlayer(player);

        pokemonRewardMap = new HashMap<>();
        for (int i = 0; i < endIndex - startIndex; i++) {
            Species species = filterSpeciesList.get(startIndex + i);
            if (species == null) {
                inventory.setItem(i, GuiItemConfig.INSTANCE.getNullPokemon());
                continue;
            }
            boolean tracked = pokedexPlayer.hasTrackedSpecies(species);
            boolean received = pokedexPlayer.hasClaimedSpeciesReward(species);
            RewardConfig.PokemonEntry pokemonReward = RewardConfig.INSTANCE.getPokemonReward(species);
            pokemonRewardMap.put(species, pokemonReward);
            ItemStack stack = tracked ? GuiItemConfig.INSTANCE.getPokemon(species, pokemonReward, received) : GuiItemConfig.INSTANCE.getAirPokemon(species, pokemonReward);
            inventory.setItem(i, stack);
        }

        for (int slot : GLASS_ARRAY) inventory.setItem(slot, GuiItemConfig.INSTANCE.getBorder());

        inventory.setItem(45, GuiItemConfig.INSTANCE.getHideAirPokemon(hideAirPokemon));
        inventory.setItem(46, GuiItemConfig.INSTANCE.getHidePokemon(hidePokemon));
        inventory.setItem(47, GuiItemConfig.INSTANCE.getHideReceivedPokemon(hideReceivedPokemon));

        inventory.setItem(49, GuiItemConfig.INSTANCE.getBack());
        inventory.setItem(48, GuiItemConfig.INSTANCE.getPreviousPage(page + 1, totalPages));
        inventory.setItem(50, GuiItemConfig.INSTANCE.getNextPage(page + 1, totalPages));
    }

    @Override
    public void onInventoryClick(ClickInventoryContext context) {
        context.setCancelled(true);
        Player player = context.getPlayer();
        int slot = context.getSlot();

        if (slot == 49) {
            new GenInventory().openInventory(player);
            player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.5F, 1F);
        } else if (slot == 48 && page > 0) {
            page--;
            onInventoryOpen(context);
            player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.5F, 1F);
        } else if (slot == 50 && page < totalPages - 1) {
            page++;
            onInventoryOpen(context);
            player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.5F, 1F);
        } else if (slot >= 0 && slot < MAX_PAGE) {
            int index = page * MAX_PAGE + slot;
            if (index < listSize) {
                Species species = filterSpeciesList.get(index);
                PokedexPlayer pokedexPlayer = LGPokedex.getPokedexPlayerManger().getPokedexPlayer(player);
                if (!pokedexPlayer.hasTrackedSpecies(species) || pokedexPlayer.hasClaimedSpeciesReward(species)) return;
                RewardConfig.PokemonEntry pokemonReward = pokemonRewardMap.get(species);
                CommandUtil.commandExecute(player, pokemonReward.commands());
                pokedexPlayer.markSpeciesRewardAsClaimed(species);
                updateSpeciesList(player);
                onInventoryOpen(context);
            }
        } else if (slot == 45) {
            hideAirPokemon = !hideAirPokemon;
            page = 0;
            updateSpeciesList(player);
            onInventoryOpen(context);
            player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_YES, 0.5F, 1F);
        } else if (slot == 46) {
            hidePokemon = !hidePokemon;
            page = 0;
            updateSpeciesList(player);
            onInventoryOpen(context);
            player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_YES, 0.5F, 1F);
        } else if (slot == 47) {
            hideReceivedPokemon = !hideReceivedPokemon;
            page = 0;
            updateSpeciesList(player);
            onInventoryOpen(context);
            player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_YES, 0.5F, 1F);
        }
    }

    @Override
    public void onInventoryClose(InventoryContext context) {
    }

    public void updateSpeciesList(Player player) {
        PokedexPlayer pokedexPlayer = LGPokedex.getPokedexPlayerManger().getPokedexPlayer(player);
        List<Species> newList = new ArrayList<>();
        for (Species species : speciesList) {
            boolean tracked = pokedexPlayer.hasTrackedSpecies(species);
            if (tracked && hidePokemon || hideAirPokemon && !tracked || hideReceivedPokemon && pokedexPlayer.hasClaimedSpeciesReward(species)) continue;
            newList.add(species);
        }
        filterSpeciesList = newList;
        updateSpeciesList();
    }

    public void updateSpeciesList() {
        listSize = filterSpeciesList.size();
        totalPages = (listSize + MAX_PAGE - 1) / MAX_PAGE;
    }

}
